package main.java.com.negromotad.view;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.regex.Pattern;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.BevelBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;

import main.java.com.negromotad.controller.DefaultController;
import main.java.com.negromotad.genetics.TMChromosome;
import main.java.com.negromotad.view.tableModelView.TableModelViewCheckBox;
import main.java.com.negromotad.view.tableModelView.TableModelViewDouble;
import main.java.com.negromotad.view.tableModelView.TableModelViewPartialResult;

public class MainView extends JFrame {
	/**
	 * 
	 */
	private static final long serialVersionUID = 2142742260192845026L;

	/**
	 * Create the application.
	 */

	public MainView(DefaultController controller) {
		setTitle("Target Motad");
		this.controller = controller;
		initialize();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		popUpConfig = new PopUpView(controller);
		aboutFrame = new About();
		this.setMinimumSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
		this.setBounds(100, 100, 501, 508);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		tabbedPane = new JTabbedPane(JTabbedPane.TOP);
		this.getContentPane().add(tabbedPane, BorderLayout.CENTER);

		// ////////////////////// PANEL 1 //////////////////////

		panel_1.setOpaque(true);
		panel_1.setLayout(new GridLayout(1, 2, 0, 0));
		panel_1.setBorder(new TitledBorder(new EtchedBorder(
				EtchedBorder.LOWERED, null, null), "Entry Data",
				TitledBorder.LEADING, TitledBorder.TOP, null,
				new Color(0, 0, 0)));
		tabbedPane.addTab("Montecarlo", null, panel_1, null);

		panel_1.setOpaque(true);
		panel_1.setBorder(new TitledBorder(UIManager
				.getBorder("TitledBorder.border"), "Entry Data",
				TitledBorder.LEADING, TitledBorder.TOP, null,
				new Color(0, 0, 0)));
		tableView2 = new TableView(null);
		tableView2.setPreferredScrollableViewportSize(new Dimension(
				PANEL_WIDTH, PANEL_HEIGHT));
		serviceCallScrollPane2 = new JScrollPane(tableView2);
		serviceCallScrollPane2.setPreferredSize(new Dimension(PANEL_WIDTH,
				PANEL_HEIGHT));
		panel_1.add(serviceCallScrollPane2);

		panel_3 = new JPanel();

		// ////////////////////// END PANEL 1 //////////////////////

		// ////////////////////// PANEL 2 //////////////////////

		panel_2 = new JPanel();
		panel_2.setName("Simulation");
		panel_2.setBorder(new TitledBorder(null, "Entry Data",
				TitledBorder.LEADING, TitledBorder.TOP, null, null));
		tabbedPane.addTab("Simulation", null, panel_2, null);
		panel_2.setLayout(new GridLayout(2, 1, 0, 0));

		tabbedPane_1 = new JTabbedPane(JTabbedPane.TOP);
		panel_2.add(tabbedPane_1);

		panel_7 = new JPanel();

		tabbedPane_1.addTab("Surface", null, panel_7, null);
		panel_7.setLayout(new GridLayout(1, 1, 0, 0));
		tableView = new TableView(null);

		tableView.setPreferredScrollableViewportSize(new Dimension(
				PANEL_WIDTH + 200, PANEL_HEIGHT));
		serviceCallScrollPane = new JScrollPane(tableView);
		serviceCallScrollPane.setPreferredSize(new Dimension(0, 0));
		panel_7.add(serviceCallScrollPane);

		panel_6 = new JPanel();
		panel_6.setLayout(new GridLayout(1, 1, 0, 0));
		tableView4 = new TableView(null);
		tableView4.setPreferredScrollableViewportSize(new Dimension(
				PANEL_WIDTH + 200, 50));
		serviceCallScrollPane4 = new JScrollPane(tableView4);
		serviceCallScrollPane4.setPreferredSize(new Dimension(
				PANEL_WIDTH + 200, 50));
		panel_6.add(serviceCallScrollPane4);
		tabbedPane_1.addTab("Others", null, panel_6, null);

		panel_8 = new JPanel();
		panel_2.add(panel_8);

		btnDaleGas = new JButton("Run");
		btnDaleGas.setEnabled(false);
		btnDaleGas.setBounds(296, 140, 64, 23);
		btnDaleGas.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent mouseevent) {
				if (btnDaleGas.isEnabled()) {
					boolean isIntegerExpectation = Pattern.matches("\\d*",
							txtExpectation.getText());
					boolean isIntegerTarget = Pattern.matches("\\d*", txtTarget
							.getText());
					if (isIntegerExpectation && isIntegerTarget && !txtTarget.getText().equals("") && !txtExpectation.getText().equals("")) {
						String target = txtTarget.getText();
						btnDaleGas.setEnabled(false);
						btnNewButton.setEnabled(false);
						btnStop.setEnabled(true);
						if (txtTarget.getText().equals("0"))
							target = "1";
						controller.startRun(Integer.parseInt(txtTarget
								.getText()), Integer.parseInt(target));
					} else {
						JOptionPane.showMessageDialog(new JFrame(),
								"Expectation or Target must be integers",
								"Error", JOptionPane.ERROR_MESSAGE);
					}
				}
			}

		});
		panel_8.setLayout(null);
		panel_8.add(btnDaleGas);
		textArea = new JTextArea();
		serviceCallScrollPane5 = new JScrollPane(textArea);
		serviceCallScrollPane5.setLocation(10, 11);
		serviceCallScrollPane5.setSize(new Dimension(263, 168));
		serviceCallScrollPane5 .setPreferredSize(new Dimension(100,
				100));
		textArea.addKeyListener(new KeyAdapter() {
			@Override
			public void keyTyped(KeyEvent arg0) {
				if (!btnStop.isEnabled()) {
					btnDaleGas.setEnabled(false);
					btnNewButton.setEnabled(true);
				}
			}
		});
		textArea.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null,
				null, null));
		textArea.setBounds(10, 11, 276, 168);
		panel_8.add(serviceCallScrollPane5);

		btnStop = new JButton("Stop");
		btnStop.setEnabled(false);
		btnStop.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent arg0) {
				if (btnStop.isEnabled()) {
					if (!btnDaleGas.isEnabled() && !btnNewButton.isEnabled()) {
						controller.stopRun();
						btnNewButton.setEnabled(true);
						btnStop.setEnabled(false);
					}
				}
			}
		});
		btnStop.setBounds(394, 140, 64, 23);
		panel_8.add(btnStop);

		btnNewButton = new JButton("Validate Rules");
		btnNewButton.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent arg0) {
				if (btnNewButton.isEnabled()) {
					if ((vars != null)) {
						resetData();
						if (panel_6.isVisible()) {
							if (controller.validRulesCA(tableModel4.getData(),
									vars, textArea.getText())) {
								btnDaleGas.setEnabled(true);
								btnNewButton.setEnabled(false);
							} else {
								JOptionPane.showMessageDialog(new JFrame(),
										"Invalid rule/rules", "Error",
										JOptionPane.ERROR_MESSAGE);
							}
						} else if (controller.validRules(textArea.getText()
								+ "\n" + getSurfaceRuleFromTable(), vars)) {
							btnDaleGas.setEnabled(true);
							btnNewButton.setEnabled(false);
						} else {
							JOptionPane.showMessageDialog(new JFrame(),
									"Invalid rule/rules", "Error",
									JOptionPane.ERROR_MESSAGE);
						}

					} else {
						JOptionPane.showMessageDialog(new JFrame(),
								"Load montecarlo data", "Error",
								JOptionPane.ERROR_MESSAGE);
					}
				}
			}

		});

		btnNewButton.setBounds(296, 93, 162, 23);
		panel_8.add(btnNewButton);

		txtExpectation = new JTextField();
		txtExpectation.setText("100");
		txtExpectation.setBounds(296, 46, 77, 20);
		panel_8.add(txtExpectation);
		txtExpectation.setColumns(10);

		txtTarget = new JTextField();
		txtTarget.setText("100");
		txtTarget.setBounds(381, 46, 77, 20);
		panel_8.add(txtTarget);
		txtTarget.setColumns(10);

		JLabel lblNewLabel_1 = new JLabel("EXPECTATION");
		lblNewLabel_1.setBounds(296, 16, 77, 14);
		panel_8.add(lblNewLabel_1);

		JLabel lblNewLabel_2 = new JLabel("TARGET");
		lblNewLabel_2.setBounds(381, 16, 46, 14);
		panel_8.add(lblNewLabel_2);
		tableView1 = new TableView(null);
		tableView1.setPreferredScrollableViewportSize(new Dimension(
				PANEL_WIDTH, PANEL_HEIGHT));
		serviceCallScrollPane1 = new JScrollPane(tableView1);
		serviceCallScrollPane1.setPreferredSize(new Dimension(PANEL_WIDTH,
				PANEL_HEIGHT));

		panel_3.setBorder(new TitledBorder(UIManager
				.getBorder("TitledBorder.border"), "Entry Data",
				TitledBorder.LEADING, TitledBorder.TOP, null,
				new Color(0, 0, 0)));
		panel_3.setLayout(new GridLayout(1, 2, 0, 0));
		panel_3.add(serviceCallScrollPane1);

		tabbedPane.addTab("Results", null, panel_3, null);

		panel = new JPanel();
		panel_3.add(panel);
		panel.setLayout(new GridLayout(2, 1, 0, 0));

		panel_4 = new JPanel();
		panel.add(panel_4);
		panel_4.setLayout(new GridLayout(3, 2, 0, 0));

		lbTotalRisk = new JLabel("Total Risk: ");
		lbTotalRisk.setBorder(new EmptyBorder(0, 5, 0, 0));
		lbTotalRisk.setAlignmentX(Component.CENTER_ALIGNMENT);
		lbTotalRisk.setHorizontalAlignment(SwingConstants.LEFT);
		lbTotalRisk.setBounds(new Rectangle(5, 5, 0, 0));
		panel_4.add(lbTotalRisk);

		totalRisk = new JLabel("0");
		panel_4.add(totalRisk);

		lbTotalSum = new JLabel("Total Sum: ");
		lbTotalSum.setBorder(new EmptyBorder(0, 5, 0, 0));
		panel_4.add(lbTotalSum);

		totalSum = new JLabel("0");
		panel_4.add(totalSum);

		panel_5 = new JPanel();
		panel.add(panel_5);
		tableView3 = new TableView(null);
		serviceCallScrollPane3 = new JScrollPane(tableView3);
		serviceCallScrollPane3
				.setPreferredSize(new Dimension(PANEL_WIDTH, 200));
		panel_5.add(serviceCallScrollPane3);

		// //////////////////////END PANEL 3 //////////////////////

		progressBar = new JProgressBar();
		this.getContentPane().add(progressBar, BorderLayout.SOUTH);

		// ////////////////// MENU ITEMS ////////////////////

		menuBar = new JMenuBar();
		this.setJMenuBar(menuBar);

		mnFile = new JMenu("File");
		menuBar.add(mnFile);

		mntmOpenFile = new JMenuItem("Open File...");
		mntmOpenFile.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent actionevent) {
				openFile(actionevent);
			}

		});
		mnFile.add(mntmOpenFile);

		mntmExit = new JMenuItem("Exit");
		mntmExit.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				System.exit(0);
			}
		});

		mntmNewMenuItem = new JMenuItem("Configuration");
		mnFile.add(mntmNewMenuItem);
		mntmNewMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				popUpConfig.setVisible(true);
			}
		});
		mnFile.add(mntmExit);

		mnHelp = new JMenu("Help");
		menuBar.add(mnHelp);

		mntmAbout = new JMenuItem("About");
		mntmAbout.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent actionevent) {
				aboutFrame.setVisible(true);
			}
		});
		mnHelp.add(mntmAbout);
	}

	private void resetData() {

		resetProgressBar();
		tableModel3 = new TableModelViewPartialResult(vars);
		tableView3.setModel(tableModel3);

		String[] headers = { "Partial Result", "Total Sum", "Evolution", "Risk" };
		tableModel1 = new TableModelViewPartialResult(headers);
		tableView1.setModel(tableModel1);

		this.updateUI();

	}

	// ///////////// END MODEL EVENTS ///////////////////////////////
	// ////////////////////////// ACTIONS ///////////////////////////
	private void openFile(ActionEvent actionevent) {
		JFileChooser fc = new JFileChooser();
		int returnVal = fc.showOpenDialog(mntmOpenFile);

		if (returnVal == JFileChooser.APPROVE_OPTION) {
			File file = fc.getSelectedFile();
			try {
				controller.loadData(file.getAbsolutePath());
				this.setTable();
				textArea.setText("");
				;

			} catch (Exception e) {
				e.printStackTrace();
			}
		}

	}

	private void setTable() {
		Double[][] row = controller.getLoader().getEntry();
		resetProgressBar();
		String[] col = (String[]) controller.getLoader().getVars().toArray(
				new String[controller.getLoader().getVars().size()]);
		this.vars = col;
		tableModel3 = new TableModelViewPartialResult(col);
		tableView3.setModel(tableModel3);

		tableModel2 = new TableModelViewDouble(col, row);
		tableView2.setModel(tableModel2);

		tableModel = new TableModelViewCheckBox(col);
		tableView.setModel(tableModel);
		tableView.getModel().addTableModelListener(tableModel);
		tableView.addPropertyChangeListener(new PropertyChangeListener() {
			public void propertyChange(PropertyChangeEvent arg0) {
				if (btnDaleGas.isEnabled()) {
					btnDaleGas.setEnabled(false);
					btnNewButton.setEnabled(true);
				}
				tableView.repaint();
			}
		});

		String[] headers = { "Partial Result", "Total Sum", "Evolution", "Risk" };
		tableModel1 = new TableModelViewPartialResult(headers);
		tableView1.setModel(tableModel1);
		Double[][] row1 = new Double[1][col.length];
		for (int i = 0; i < col.length; i++) {
			row1[0][i] = new Double(0.0);
		}
		String[] colAux = new String[this.vars.length];
		for (int i = 0; i < colAux.length; i++) {
			colAux[i] = "CA_" + this.vars[i];
		}
		tableModel4 = new TableModelViewDouble(colAux, row1);
		tableModel4.setFirstColName("Costo Asociado");
		tableView4.setModel(tableModel4);
		this.updateUI();

	}

	public void resetProgressBar() {
		totalRisk.setText("0");
		totalSum.setText("0");
		progressBar.setMinimum(0);
		progressBar.setMaximum(popUpConfig.getMaximumProgressBar());
		progressBar.setValue(0);
		progressBar.updateUI();
		progressBar.repaint();

	}

	private void updateUI() {
		tableView2.updateUI();
		tableView2.repaint();
		tableView.updateUI();
		tableView.repaint();
		tableView1.repaint();
		tableView1.updateUI();
		tableView3.repaint();
		tableView3.updateUI();
		tableView4.updateUI();
		tableView4.repaint();
	}

	public String getSurfaceRuleFromTable() {
		Object[][] grid = tableModel.getData();
		int cols = tableModel.getColumnCount();
		Boolean[] vars = new Boolean[cols];
		boolean cb = false;
		for (int i = 1; i < cols; i++) {
			vars[i] = false;
			for (int j = 1; j < 13; j++) {
				cb = (Boolean) grid[j][i];
				if (cb) {
					vars[i] = true;
				}
			}
		}
		String rule = "";
		for (int i = 1; i < vars.length; i++) {
			if (vars[i]) {
				rule = rule + tableModel.getColumnName(i) + "+";
			}
		}
		if (rule != "") {
			rule = rule.substring(0, rule.length() - 1);
			rule = rule + "<100"; // TODO FIX PEPE HDP!
		}
		return rule;
	}

	public void addResultRow(Integer[] resultsDouble) {
		String[] results = new String[vars.length];
		for (int i = 0; i < resultsDouble.length; i++) {
			results[i] = Double.toString(resultsDouble[i]);
		}
		tableModel3.addRow(results);
		tableView3.updateUI();
		tableView3.repaint();
		btnStop.setEnabled(false);
		btnNewButton.setEnabled(true);

	}

	public void addPartialResultRow(double total, int evolution,
			String partialResult, double risk) {
		String[] partialResults = new String[4];
		partialResults[0] = partialResult;
		partialResults[1] = Double.toString(total);
		partialResults[2] = Integer.toString(evolution);
		partialResults[3] = Double.toString(risk);
		tableModel1.addRow(partialResults);
		tableView1.updateUI();
		tableView1.repaint();
		progressBar.setValue(tableModel1.getData().length);

	}

	public void setFinalResults(double totalRisk, double totalSum) {
		this.totalRisk.setText(Double.toString(totalRisk));
		this.totalSum.setText(Double.toString(totalSum));

	}

	public void failure(TMChromosome chromosome) {
			JOptionPane.showMessageDialog(new JFrame(),
					"Max failure evolutions reached. Stopping algorithm",
					"Error", JOptionPane.ERROR_MESSAGE);
		btnStop.setEnabled(false);
		btnNewButton.setEnabled(true);
	}

	public void reached() {
		JOptionPane.showMessageDialog(new JFrame(),
				"Max evolutions reached with same result. Stopping algorithm",
				"Alert", JOptionPane.ERROR_MESSAGE);

	}

	// ////////////////////////// END ACTIONS
	// /////////////////////////////////////////////
	private DefaultController controller;
	private PopUpView popUpConfig;
	private About aboutFrame;
	private JPanel panel_1 = new JPanel();
	private JTabbedPane tabbedPane;
	private JPanel panel_2;
	private JTabbedPane tabbedPane_1;
	private JPanel panel_7;
	private TableModelViewCheckBox tableModel;
	private TableView tableView;
	private JScrollPane serviceCallScrollPane;
	private JScrollPane serviceCallScrollPane5;
	private JScrollPane serviceCallScrollPane2;
	private JScrollPane serviceCallScrollPane4;
	private TableView tableView4;
	private TableModelViewDouble tableModel4;
	private TableView tableView2;
	private TableModelViewDouble tableModel2;
	private TableModelViewPartialResult tableModel1;
	private TableModelViewPartialResult tableModel3;
	private JPanel panel_8;
	private JPanel panel_3;
	private TableView tableView1;
	private JScrollPane serviceCallScrollPane1;
	private JPanel panel;
	private JPanel panel_4;
	private JPanel panel_5;
	private JProgressBar progressBar;
	private JMenuBar menuBar;
	private JMenu mnFile;
	private JMenuItem mntmOpenFile;
	private JMenuItem mntmExit;
	private JMenu mnHelp;
	private JMenuItem mntmNewMenuItem;
	private JMenuItem mntmAbout;
	private JButton btnDaleGas;
	private JTextArea textArea;
	private JButton btnStop;
	private JButton btnNewButton;
	private JScrollPane serviceCallScrollPane3;
	private TableView tableView3;
	String[] vars = null;
	private final static int PANEL_HEIGHT = 400;
	private final static int PANEL_WIDTH = 250;
	private JPanel panel_6;
	private JTextField txtExpectation;
	private JTextField txtTarget;
	private JLabel lbTotalRisk;
	private JLabel lbTotalSum;
	private JLabel totalRisk;
	private JLabel totalSum;

}
